package com.ruoyi.system.service.impl;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.bean.BeanUtils;
import com.ruoyi.system.constant.AuditActionConstant;
import com.ruoyi.system.constant.AuditStatusConstant;
import com.ruoyi.system.domain.AuditAssignee;
import com.ruoyi.system.domain.AuditNode;
import com.ruoyi.system.service.IAuditAssigneeService;
import com.ruoyi.system.service.IAuditNodeService;
import com.ruoyi.system.service.ISysUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ruoyi.system.mapper.AuditRouteMapper;
import com.ruoyi.system.domain.AuditRoute;
import com.ruoyi.system.service.IAuditRouteService;

import javax.annotation.Resource;

/**
 * 审核路径实例（节点级）Service业务层处理
 * 
 * @author ruoyi
 * @date 2025-11-07
 */
@Service
public class AuditRouteServiceImpl extends ServiceImpl<AuditRouteMapper, AuditRoute> implements IAuditRouteService
{
    @Autowired
    private AuditRouteMapper auditRouteMapper;
    @Resource
    private IAuditNodeService auditNodeService;
    @Resource
    private ISysUserService userService;
    @Resource
    private IAuditAssigneeService auditAssigneeService;

    /**
     * 查询审核路径实例（节点级）
     * 
     * @param auditRouteId 审核路径实例（节点级）主键
     * @return 审核路径实例（节点级）
     */
    @Override
    public AuditRoute selectAuditRouteByAuditRouteId(Long auditRouteId)
    {
        return auditRouteMapper.selectAuditRouteByAuditRouteId(auditRouteId);
    }

    /**
     * 查询审核路径实例（节点级）列表
     * 
     * @param auditRoute 审核路径实例（节点级）
     * @return 审核路径实例（节点级）
     */
    @Override
    public List<AuditRoute> selectAuditRouteList(AuditRoute auditRoute)
    {
        return auditRouteMapper.selectAuditRouteList(auditRoute);
    }

    /**
     * 新增审核路径实例（节点级）
     * 
     * @param auditRoute 审核路径实例（节点级）
     * @return 结果
     */
    @Override
    public int insertAuditRoute(AuditRoute auditRoute)
    {
        auditRoute.setCreateTime(DateUtils.getNowDate());
        return auditRouteMapper.insertAuditRoute(auditRoute);
    }
    
    /**
     * 批量新增审核路径实例（节点级）
     * 
     * @param auditRoutes 审核路径实例（节点级）列表
     * @return 结果
     */
    @Override
    public int insertAuditRoutes(List<AuditRoute> auditRoutes)
    {
        for (AuditRoute auditRoute : auditRoutes) {
            auditRoute.setCreateTime(DateUtils.getNowDate());
        }
        this.saveBatch(auditRoutes);
        return auditRoutes.size();
    }

    /**
     * 修改审核路径实例（节点级）
     * 
     * @param auditRoute 审核路径实例（节点级）
     * @return 结果
     */
    @Override
    public int updateAuditRoute(AuditRoute auditRoute)
    {
        auditRoute.setUpdateTime(DateUtils.getNowDate());
        return auditRouteMapper.updateAuditRoute(auditRoute);
    }

    /**
     * 批量删除审核路径实例（节点级）
     * 
     * @param auditRouteIds 需要删除的审核路径实例（节点级）主键
     * @return 结果
     */
    @Override
    public int deleteAuditRouteByAuditRouteIds(String[] auditRouteIds)
    {
        return auditRouteMapper.deleteAuditRouteByAuditRouteIds(auditRouteIds);
    }

    /**
     * 删除审核路径实例（节点级）信息
     * 
     * @param auditRouteId 审核路径实例（节点级）主键
     * @return 结果
     */
    @Override
    public int deleteAuditRouteByAuditRouteId(String auditRouteId)
    {
        return auditRouteMapper.deleteAuditRouteByAuditRouteId(auditRouteId);
    }

    /**
     * 处理审批流程
     */
    @Override
    public Long initAuditRoute(String auditBusinessType, Long businessId) {
        // 根据auditBusinessType查询audit_node
        List<AuditNode> auditNodes = auditNodeService.noPageList(auditBusinessType);

        if (auditNodes == null || auditNodes.isEmpty()) {
            throw new ServiceException("未配置审批流程");
        }

        // 收集所有需要插入的audit_route和audit_assignee
        List<AuditRoute> routeList = new ArrayList<>();
        List<AuditAssignee> assigneeList = new ArrayList<>();

        // 遍历auditNodes，创建audit_route和audit_assignee
        for (AuditNode auditNode : auditNodes) {
            AuditRoute auditRoute = new AuditRoute();
            // 使用BeanUtils简化对象属性复制
            BeanUtils.copyBeanProp(auditRoute, auditNode);
            auditRoute.setBusinessId(businessId);
            auditRoute.setRoundNo(1); // 默认第一轮
            auditRoute.setAuditStatus(AuditStatusConstant.PENDING); // 待审核状态
            routeList.add(auditRoute);

            // 检查审批角色是否有用户，如果没有则抛出异常
            List<SysUser> auditUsers = userService.selectUserListByRoleId(auditNode.getAuditRoleId());
            if (auditUsers == null || auditUsers.isEmpty()) {
                throw new ServiceException("角色ID为" + auditNode.getAuditRoleId() + "的审批角色没有分配用户");
            }

            // 创建审批人audit_assignee
            for (SysUser auditUser : auditUsers) {
                AuditAssignee auditAssignee = new AuditAssignee();
                auditAssignee.setBusinessId(businessId);
                auditAssignee.setAuditBusinessType(auditBusinessType);
                // auditRouteId会在批量插入后设置
                auditAssignee.setUserId(auditUser.getUserId());
                auditAssignee.setActionType(AuditActionConstant.AUDIT); // 1 审批
                auditAssignee.setAuditStatus(AuditStatusConstant.PENDING); // 0 待审核
                auditAssignee.setRoundNo(auditRoute.getRoundNo());
                assigneeList.add(auditAssignee);
            }

            // 处理抄送人
            if (StringUtils.isNotEmpty(auditNode.getCopyRoleIds())) {
                String[] copyRoleIds = auditNode.getCopyRoleIds().split(",");
                for (String roleId : copyRoleIds) {
                    Long copyRoleId = Long.valueOf(roleId.trim());
                    List<SysUser> copyUsers = userService.selectUserListByRoleId(copyRoleId);

                    for (SysUser copyUser : copyUsers) {
                        AuditAssignee copyAssignee = new AuditAssignee();
                        copyAssignee.setBusinessId(businessId);
                        copyAssignee.setAuditBusinessType(auditBusinessType);
                        // auditRouteId会在批量插入后设置
                        copyAssignee.setUserId(copyUser.getUserId());
                        copyAssignee.setActionType(AuditActionConstant.COPY); // 2 抄送
                        copyAssignee.setAuditStatus(AuditStatusConstant.PENDING); // 0 待审核
                        copyAssignee.setRoundNo(auditRoute.getRoundNo());
                        assigneeList.add(copyAssignee);
                    }
                }
            }
        }

        // 批量插入audit_route
        this.insertAuditRoutes(routeList);

        // 建立audit_node与audit_route的映射关系，用于设置audit_assignee的auditRouteId
        Map<AuditNode, AuditRoute> nodeRouteMap = new HashMap<>();
        for (int i = 0; i < auditNodes.size(); i++) {
            nodeRouteMap.put(auditNodes.get(i), routeList.get(i));
        }

        // 设置assigneeList中每个assignee的auditRouteId
        int assigneeIndex = 0;
        for (AuditNode auditNode : auditNodes) {
            AuditRoute auditRoute = nodeRouteMap.get(auditNode);

            // 设置审批人audit_assignee的auditRouteId
            List<SysUser> auditUsers = userService.selectUserListByRoleId(auditNode.getAuditRoleId());
            for (int i = 0; i < auditUsers.size(); i++) {
                assigneeList.get(assigneeIndex++).setAuditRouteId(auditRoute.getAuditRouteId());
            }

            // 设置抄送人audit_assignee的auditRouteId
            if (StringUtils.isNotEmpty(auditNode.getCopyRoleIds())) {
                String[] copyRoleIds = auditNode.getCopyRoleIds().split(",");
                for (String roleId : copyRoleIds) {
                    Long copyRoleId = Long.valueOf(roleId.trim());
                    List<SysUser> copyUsers = userService.selectUserListByRoleId(copyRoleId);
                    for (int i = 0; i < copyUsers.size(); i++) {
                        assigneeList.get(assigneeIndex++).setAuditRouteId(auditRoute.getAuditRouteId());
                    }
                }
            }
        }

        // 批量插入audit_assignee
        auditAssigneeService.insertAuditAssignees(assigneeList);

        // 返回当前审核路径ID为第一个节点的ID（即第一个audit_route）
        return routeList.get(0).getAuditRouteId();
    }
    
    /**
     * 根据审核业务类型和业务ID查询审核路径实例列表（包含审核人信息）
     * 
     * @param auditBusinessType 审核业务类型
     * @param businessId 业务ID
     * @return 审核路径实例集合
     */
    @Override
    public List<AuditRoute> selectAuditRoutesByBusinessTypeAndBusinessId(String auditBusinessType, Long businessId) {
        return auditRouteMapper.selectAuditRoutesByBusinessTypeAndBusinessId(auditBusinessType, businessId);
    }
    
    /**
     * 根据审核业务类型和业务ID查询审核路径实例列表（包含审核人信息），按轮次分组
     *
     * @param auditBusinessType 审核业务类型
     * @param businessId 业务ID
     * @return 审核路径实例集合，按轮次分组排序
     */
    @Override
    public List<AuditRoute> selectAuditRoutesByBusinessTypeAndBusinessIdGroupByRound(String auditBusinessType, Long businessId) {
        return auditRouteMapper.selectAuditRoutesByBusinessTypeAndBusinessIdGroupByRound(auditBusinessType, businessId);
    }

    @Override
    public List<AuditRoute> selectRollbackOptions(Long businessId, String auditBusinessType, Long currentRouteId) {
        if (businessId == null || currentRouteId == null) {
            return Collections.emptyList();
        }

        AuditRoute currentRoute = selectAuditRouteByAuditRouteId(currentRouteId);
        if (currentRoute == null || currentRoute.getAuditOrder() == null) {
            return Collections.emptyList();
        }

        Integer maxOrder = currentRoute.getAuditOrder();
        List<AuditRoute> candidates = auditRouteMapper.selectRollbackCandidates(businessId, auditBusinessType, maxOrder);
        if (candidates == null || candidates.isEmpty()) {
            return Collections.emptyList();
        }

        LinkedHashMap<Integer, AuditRoute> distinctByOrder = new LinkedHashMap<>();
        for (AuditRoute route : candidates) {
            if (route == null || route.getAuditOrder() == null) {
                continue;
            }
            int order = route.getAuditOrder();
            if (order >= maxOrder) {
                continue;
            }
            distinctByOrder.putIfAbsent(order, route);
        }
        return new ArrayList<>(distinctByOrder.values());
    }
}